package com.lap.generator.domain.valueobject;

import com.lap.generator.commons.enums.AnnotationType;
import com.lap.generator.commons.tools.TextUtil;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Optional;
import lombok.AccessLevel;
import lombok.Builder;
import lombok.Data;
import lombok.Getter;

@Builder
@Data
public class FieldModel {
  // 数据库字段
  /** 原始数据库字段 */
  private String columnName;

  /** 数据库字段类型 */
  private String columnType;

  /** java 类型 */
  private ModelType modelType;

  // java字段
  /** 小写驼峰属性名 */
  private String fieldName;

  /** 注释 */
  private String comment;

  /** ModelType 枚举映射 */
  @Getter(AccessLevel.NONE)
  private String javaType;

  // 额外属性
  /** 字段为空 */
  private boolean nullable;

  private boolean ignoreEntity;
  private boolean dateField;
  private boolean ignoreInsert;
  private boolean ignoreUpdate;

  /** 国际化键名或默认错误提示 */
  @Getter(AccessLevel.NONE)
  private List<String> errorMessages;

  /** 如 @NotNull, @Size(max=50) */
  @Getter(AccessLevel.NONE)
  private List<String> annotations;

  public List<String> getAnnotations() {
    if (annotations == null) annotations = new ArrayList<>();
    return annotations;
  }

  public List<String> getErrorMessages() {
    if (errorMessages == null) errorMessages = new ArrayList<>();
    return errorMessages;
  }

  public String getJavaType() {
    return Optional.ofNullable(modelType)
        .map(ModelType::javaType)
        .map(JavaType::getCode)
        .orElse(null);
  }

  public void addNotNullValidation(String parentCode, String[] excludeField) {
    if (Arrays.stream(excludeField).anyMatch(item -> item.equalsIgnoreCase(this.columnName)))
      return;

    if (!isNullable()) {
      String i18nKey = getI18nKey(parentCode, fieldName, ValidationType.REQUIRED);
      String annotation =
          JavaType.eqStr(modelType.javaType())
              ? String.format(AnnotationType.NOT_BLANK.getValue(), i18nKey)
              : String.format(AnnotationType.NOT_NULL.getValue(), i18nKey);
      getAnnotations().add(annotation);
      getErrorMessages().add(String.format("%s=%s不能为空", i18nKey, TextUtil.resolverText(comment)));
    }
  }

  public void addLengthValidation(String parentCode, String[] excludeField) {
    String i18nKey;
    String annotation;
    if (Arrays.stream(excludeField).anyMatch(item -> item.equalsIgnoreCase(this.columnName)))
      return;

    if (JavaType.eqNumber(modelType.javaType())) {
      i18nKey = getI18nKey(parentCode, fieldName, ValidationType.RANGE);
      annotation =
          String.format(
              AnnotationType.NUMBER_RANGE.getValue(), modelType.min(), modelType.max(), i18nKey);
      getAnnotations().add(annotation);
      getErrorMessages()
          .add(String.format("%s=%s值在{min}和{max}间", i18nKey, TextUtil.resolverText(comment)));
    } else if (JavaType.eqStr(modelType.javaType())) {
      i18nKey = getI18nKey(parentCode, fieldName, ValidationType.MAX_LENGTH);
      annotation = String.format(AnnotationType.LENGTH.getValue(), modelType.max(), i18nKey);
      getAnnotations().add(annotation);
      getErrorMessages()
          .add(String.format("%s=%s长度不能超过{max}", i18nKey, TextUtil.resolverText(comment)));
    }
  }

  private String getI18nKey(String parentCode, String fieldCode, ValidationType suffixMessage) {
    return String.format("%s.%s.%s", parentCode, fieldCode, suffixMessage.getSuffix());
  }

  public void setIgnoreField(String[] excludeField) {
    this.ignoreEntity =
        Arrays.stream(excludeField).anyMatch(item -> item.equalsIgnoreCase(columnName));
  }

  public void setDateField(String[] excludeField) {
    this.dateField =
        Arrays.stream(excludeField)
            .anyMatch(
                item ->
                    (JavaType.isDate(modelType.javaType()) && item.equalsIgnoreCase(columnName)));
  }

  public void setIgnoreInsert(String[] ignoreInsert) {
    this.ignoreInsert =
        Arrays.stream(ignoreInsert).anyMatch(item -> columnName.equalsIgnoreCase(item));
  }

  public void setIgnoreUpdate(String[] ignoreUpdate) {
    this.ignoreUpdate =
        Arrays.stream(ignoreUpdate).anyMatch(item -> columnName.equalsIgnoreCase(item));
  }

  // 可以枚举验证类型，减少硬编码
  @Getter
  public enum ValidationType {
    REQUIRED("required"),
    RANGE("range"),
    MAX_LENGTH("max.length");

    private final String suffix;

    ValidationType(String suffix) {
      this.suffix = suffix;
    }
  }
}
